import json

from ev import Command
from src.server.jsprocpool import ExecuteJavaScript
from src.utils import logger
from twisted.python import log # For Errback.

_SESSIONS = None
class CmdJS(Command):
    """
    A command to execute remote JavaScript code via the JSProcPool.

    Usage:
    @js <code>

    Executes JavaScript code via the JSProcPool if available. In a real system, 
    one might launch JavaScript in a number of ways. This code demonstrates how
    to find and access the pool.
    """

    key = "@js"
    locks = "cmd:all()"
    help_category = "System"

    # A class variable to avoid searching for the pool more than once.
    # This could also have been done with a global.
    _jsppool = None

    def _pool_load_helper(self):
        global _SESSIONS
        """Helper method demonstrating how to load the Process Pool."""
        if CmdJS._jsppool == None:
            from src.server.sessionhandler import SESSIONS as _SESSIONS
        try:
            CmdJS._jsppool = _SESSIONS.server.services.namedServices.get("JSProcPool").pool
        except AttributeError:
            CmdJS._jsppool = False

    def func(self):
        """Find the proc pool and use it if possible. The service discovery code is
        based on utils.run_async."""
        self._pool_load_helper()
        if not CmdJS._jsppool:
            caller.msg("JavaScript subsystem not loaded.")
            return
        caller = self.caller
        # Construct our arguments properly. We need a json-serialized env.
        environment = json.dumps({'me' : caller.dbref, 'here' : caller.location.dbref})
        source = self.args.encode("utf8")

        deferred = CmdJS._jsppool.doWork(ExecuteJavaScript, environment=environment,
                                    source=source)
        # We now have our deferred for the javascript state. If you wanted
        # to handle errors or designed a protocol which had return codes, this
        # would be the place to register callbacks. For now, just log things.
        # Eventually, Evennia should supply a suitable generic error callback.
        deferred.addErrback(log.err)